package com.zenithmind.task.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.utils.BeanCopyUtils;
import com.zenithmind.task.mapper.TaskDependencyMapper;
import com.zenithmind.task.pojo.entity.TaskDependency;
import com.zenithmind.task.pojo.query.TaskDependencyQuery;
import com.zenithmind.task.pojo.vo.TaskDependencyVO;
import com.zenithmind.task.service.TaskDependencyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 任务依赖服务实现类
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TaskDependencyServiceImpl extends ServiceImpl<TaskDependencyMapper, TaskDependency> implements TaskDependencyService {

    @Override
    public PageResult<TaskDependencyVO> getTaskDependencyPage(TaskDependencyQuery query, String userId) {
        Page<TaskDependency> page = query.toPage();

        LambdaQueryWrapper<TaskDependency> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.hasText(query.getPredecessorId()), TaskDependency::getPredecessorId, query.getPredecessorId())
               .eq(StringUtils.hasText(query.getSuccessorId()), TaskDependency::getSuccessorId, query.getSuccessorId())
               .eq(query.getDependencyType() != null, TaskDependency::getDependencyType, query.getDependencyType())
               .eq(query.getStatus() != null, TaskDependency::getStatus, query.getStatus());

        // 时间范围查询
        if (query.getCreateTimeBegin() != null) {
            wrapper.ge(TaskDependency::getCreateTime, query.getCreateTimeBegin());
        }
        if (query.getCreateTimeEnd() != null) {
            wrapper.le(TaskDependency::getCreateTime, query.getCreateTimeEnd());
        }

        wrapper.orderByDesc(TaskDependency::getCreateTime);

        IPage<TaskDependency> result = page(page, wrapper);

        List<TaskDependencyVO> voList = result.getRecords().stream()
            .map(this::convertToVO)
            .collect(Collectors.toList());

        return PageResult.of(voList, result.getTotal());
    }

    @Override
    public TaskDependencyVO getTaskDependencyById(String id, String userId) {
        TaskDependency taskDependency = getById(id);
        if (taskDependency == null) {
            throw new BusinessException("任务依赖不存在");
        }
        
        return convertToVO(taskDependency);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createTaskDependency(TaskDependency taskDependency, String userId) {
        // 检查循环依赖
        if (checkCircularDependency(taskDependency.getPredecessorId(), taskDependency.getSuccessorId())) {
            throw new BusinessException("创建依赖会形成循环依赖，无法创建");
        }

        // 检查是否已存在相同的依赖
        LambdaQueryWrapper<TaskDependency> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskDependency::getPredecessorId, taskDependency.getPredecessorId())
               .eq(TaskDependency::getSuccessorId, taskDependency.getSuccessorId())
               .eq(TaskDependency::getStatus, 1); // 有效状态

        if (count(wrapper) > 0) {
            throw new BusinessException("该依赖关系已存在");
        }

        // 设置默认值
        if (taskDependency.getStatus() == null) {
            taskDependency.setStatus(1); // 有效
        }
        if (taskDependency.getDependencyType() == null) {
            taskDependency.setDependencyType(1); // 完成-开始
        }
        if (taskDependency.getLagDays() == null) {
            taskDependency.setLagDays(0);
        }

        taskDependency.setCreatorId(userId);

        boolean result = save(taskDependency);
        
        if (result) {
            log.info("用户 {} 创建任务依赖: 前置任务ID={}, 后续任务ID={}", userId, taskDependency.getPredecessorId(), taskDependency.getSuccessorId());
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateTaskDependency(TaskDependency taskDependency, String userId) {
        TaskDependency existing = getById(taskDependency.getId());
        if (existing == null) {
            throw new BusinessException("任务依赖不存在");
        }

        // 权限检查
        if (!existing.getCreatorId().equals(userId)) {
            throw new BusinessException("无权限修改该任务依赖");
        }

        boolean result = updateById(taskDependency);
        
        if (result) {
            log.info("用户 {} 更新任务依赖: ID={}", userId, taskDependency.getId());
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteTaskDependency(String id, String userId) {
        TaskDependency taskDependency = getById(id);
        if (taskDependency == null) {
            throw new BusinessException("任务依赖不存在");
        }

        // 权限检查
        if (!taskDependency.getCreatorId().equals(userId)) {
            throw new BusinessException("无权限删除该任务依赖");
        }

        boolean result = removeById(id);
        
        if (result) {
            log.info("用户 {} 删除任务依赖: ID={}", userId, id);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeleteTaskDependencies(List<String> ids, String userId) {
        for (String id : ids) {
            deleteTaskDependency(id, userId);
        }
        return true;
    }

    @Override
    public List<TaskDependencyVO> getTaskPredecessors(String taskId, String userId) {
        LambdaQueryWrapper<TaskDependency> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskDependency::getSuccessorId, taskId)
               .eq(TaskDependency::getStatus, 1)
               .orderByAsc(TaskDependency::getLagDays);

        List<TaskDependency> dependencies = list(wrapper);
        
        return dependencies.stream()
            .map(this::convertToVO)
            .collect(Collectors.toList());
    }

    @Override
    public List<TaskDependencyVO> getTaskSuccessors(String taskId, String userId) {
        LambdaQueryWrapper<TaskDependency> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskDependency::getPredecessorId, taskId)
               .eq(TaskDependency::getStatus, 1)
               .orderByAsc(TaskDependency::getLagDays);

        List<TaskDependency> dependencies = list(wrapper);
        
        return dependencies.stream()
            .map(this::convertToVO)
            .collect(Collectors.toList());
    }

    @Override
    public Boolean checkCircularDependency(String predecessorId, String successorId) {
        // 使用深度优先搜索检查循环依赖
        Set<String> visited = new HashSet<>();
        return dfsCheckCircular(successorId, predecessorId, visited);
    }

    @Override
    public List<List<TaskDependencyVO>> getTaskDependencyPath(String taskId, String userId) {
        List<List<TaskDependencyVO>> paths = new ArrayList<>();
        
        // 获取所有前置依赖路径
        List<TaskDependencyVO> predecessors = getTaskPredecessors(taskId, userId);
        for (TaskDependencyVO predecessor : predecessors) {
            List<TaskDependencyVO> path = new ArrayList<>();
            path.add(predecessor);
            buildDependencyPath(predecessor.getPredecessorId(), path, paths, userId, true);
        }
        
        return paths;
    }

    /**
     * 深度优先搜索检查循环依赖
     */
    private boolean dfsCheckCircular(String currentTaskId, String targetTaskId, Set<String> visited) {
        if (currentTaskId.equals(targetTaskId)) {
            return true; // 找到循环
        }
        
        if (visited.contains(currentTaskId)) {
            return false; // 已访问过，避免无限循环
        }
        
        visited.add(currentTaskId);
        
        // 查找当前任务的所有前置任务
        LambdaQueryWrapper<TaskDependency> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskDependency::getSuccessorId, currentTaskId)
               .eq(TaskDependency::getStatus, 1);
        
        List<TaskDependency> dependencies = list(wrapper);
        
        for (TaskDependency dependency : dependencies) {
            if (dfsCheckCircular(dependency.getPredecessorId(), targetTaskId, visited)) {
                return true;
            }
        }
        
        visited.remove(currentTaskId);
        return false;
    }

    /**
     * 构建依赖路径
     */
    private void buildDependencyPath(String taskId, List<TaskDependencyVO> currentPath, 
                                   List<List<TaskDependencyVO>> allPaths, String userId, boolean isPredecessor) {
        List<TaskDependencyVO> dependencies = isPredecessor ? 
            getTaskPredecessors(taskId, userId) : getTaskSuccessors(taskId, userId);
        
        if (dependencies.isEmpty()) {
            // 到达路径末端，添加到结果中
            allPaths.add(new ArrayList<>(currentPath));
            return;
        }
        
        for (TaskDependencyVO dependency : dependencies) {
            List<TaskDependencyVO> newPath = new ArrayList<>(currentPath);
            newPath.add(dependency);
            
            String nextTaskId = isPredecessor ? dependency.getPredecessorId() : dependency.getSuccessorId();
            buildDependencyPath(nextTaskId, newPath, allPaths, userId, isPredecessor);
        }
    }

    /**
     * 转换为VO对象
     */
    private TaskDependencyVO convertToVO(TaskDependency taskDependency) {
        TaskDependencyVO vo = BeanCopyUtils.copyBean(taskDependency, TaskDependencyVO.class);
        
        // 设置依赖类型文本
        vo.setDependencyTypeText(getDependencyTypeText(taskDependency.getDependencyType()));
        
        // 设置状态文本
        vo.setStatusText(getStatusText(taskDependency.getStatus()));
        
        return vo;
    }

    /**
     * 获取依赖类型文本
     */
    private String getDependencyTypeText(Integer dependencyType) {
        switch (dependencyType) {
            case 1: return "完成-开始";
            case 2: return "开始-开始";
            case 3: return "完成-完成";
            case 4: return "开始-完成";
            default: return "未知";
        }
    }

    /**
     * 获取状态文本
     */
    private String getStatusText(Integer status) {
        switch (status) {
            case 1: return "有效";
            case 0: return "无效";
            default: return "未知";
        }
    }
}
